package coc.example.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;

import org.springframework.stereotype.Service;

import coo.base.exception.UncheckedException;
import coo.base.model.Params;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;

@Service
public class ScriptTemplateManager {
	private Configuration configuration;

	/**
	 * 构造方法。
	 */
	public ScriptTemplateManager() {
		configuration = new Configuration(new Version(2, 3, 21));
		configuration.setDefaultEncoding("UTF-8");
		configuration.setURLEscapingCharset("UTF-8");
		configuration.setDateTimeFormat("yyyy-MM-dd HH:mm:ss");
		configuration.setDateFormat("yyyy-MM-dd");
		configuration.setTimeFormat("HH:mm:ss");
		configuration.setNumberFormat("#");
		configuration.setBooleanFormat("true,false");
		configuration.setClassicCompatible(true);
		try {
			TemplateLoader[] templateLoaders = new TemplateLoader[] {
					new BshFileTemplateLoader(Dirs.COMMONS.getPath()),
					new BshFileTemplateLoader(Dirs.CRAWLER.getPath()) };
			configuration.setTemplateLoader(new MultiTemplateLoader(
					templateLoaders));
		} catch (Exception e) {
			throw new UncheckedException("设定脚本模版目录时发生异常。", e);
		}
	}

	/**
	 * 根据脚本名称和浮动参数生成完整的爬虫脚本。
	 * 
	 * @param scriptName
	 *            脚本名称
	 * @param floatParams
	 *            浮动参数
	 * @return 返回生成的爬虫脚本。
	 */
	public String getScript(String scriptName, Params floatParams) {
		try {
			Template template = configuration.getTemplate(scriptName);
			Writer out = new StringWriter();
			template.process(floatParams, out);
			return out.toString();
		} catch (Exception e) {
			throw new UncheckedException("生成爬虫脚本时发生异常。", e);
		}
	}

	private class BshFileTemplateLoader implements TemplateLoader {
		private String dir;

		public BshFileTemplateLoader(String dir) throws IOException {
			this.dir = dir;
		}

		@Override
		public Object findTemplateSource(String name) throws IOException {
			File file = new File(dir + "/" + name + ".bsh");
			if (file.exists()) {
				return file;
			} else {
				return null;
			}
		}

		@Override
		public long getLastModified(Object templateSource) {
			return ((File) templateSource).lastModified();
		}

		@Override
		public Reader getReader(Object templateSource, String encoding)
				throws IOException {
			return new InputStreamReader(new FileInputStream(
					(File) templateSource), encoding);
		}

		@Override
		public void closeTemplateSource(Object templateSource)
				throws IOException {
		}
	}
}
